<template>
    <div class="backtest-tool">
      <h2>基金网格交易回测工具</h2>
      <!-- 用户参数设置 -->
      <div class="controls">
        <label>起始日期:
          <input type="date" v-model="startDate" />
        </label>
        <label>结束日期:
          <input type="date" v-model="endDate" />
        </label>
        <label>网格卖出涨幅比例 (%):
          <input type="number" v-model.number="sellThreshold" />
        </label>
        <label>网格买入跌幅比例 (%):
          <input type="number" v-model.number="buyThreshold" />
        </label>
        <label>计划总本金:
          <input type="number" v-model.number="totalCapital" />
        </label>
        <label>分成份数:
          <input type="number" v-model.number="parts" />
        </label>
        <label>低仓比例 (%):
          <input type="number" v-model.number="lowPositionRatio" />
        </label>
        <button @click="runBacktest">开始回测</button>
      </div>
  
      <!-- 汇总信息 -->
      <div class="summary" v-if="summary">
        <h3>回测结果总结</h3>
        <p>定投总金额：{{ summary.totalInvested.toFixed(2) }}</p>
        <p>累计收益：{{ summary.totalProfit.toFixed(2) }}</p>
        <p>持有天数：{{ summary.holdingDays }}</p>
        <p>总资产：{{ summary.totalAsset.toFixed(2) }}</p>
        <p>总投资收益率：{{ (summary.totalYield * 100).toFixed(2) }}%</p>
      </div>
  
      <!-- 每日数据表格 -->
      <table v-if="result.length">
        <thead>
          <tr>
            <th>日期</th>
            <th>操作</th>
            <th>加仓/减仓情况</th>
            <th>持仓份额</th>
            <th>持仓价值</th>
            <th>投入本金</th>
            <th>当日收益</th>
            <th>持仓收益率</th>
            <th>当天涨跌幅</th>
            <th>累积收益</th>
            <th>网格累计收益率</th>
            <th>总投资收益率</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(row, idx) in result" :key="idx">
            <td>{{ row.date }}</td>
            <td>{{ row.operation }}</td>
            <td>{{ row.tradeAmount }}</td>
            <td>{{ row.holdShares }}</td>
            <td>{{ row.holdValue.toFixed(2) }}</td>
            <td>{{ row.invested.toFixed(2) }}</td>
            <td>{{ row.dailyReturn.toFixed(2) }}</td>
            <td>{{ (row.holdYield * 100).toFixed(2) }}%</td>
            <td>{{ row.dailyChange.toFixed(2) }}%</td>
            <td>{{ row.totalProfit.toFixed(2) }}</td>
            <td>{{ (row.gridCumulativeYield * 100).toFixed(2) }}%</td>
            <td>{{ (row.totalYield * 100).toFixed(2) }}%</td>
          </tr>
        </tbody>
      </table>
  
      <!-- ECharts 折线图 -->
      <div ref="chart" style="width: 100%; height: 400px; margin-top:20px;"></div>
    </div>
  </template>
  
  <script>
  import { nextTick } from 'vue'
  import data from '../../../assets/json/data.json'
  import * as echarts from 'echarts'
  
  export default {
    name: 'GridBacktestTool',
    data() {
      return {
        // 用户自定义参数
        startDate: '',
        endDate: '',
        sellThreshold: 4.5,   // 卖出触发阈值（%）
        buyThreshold: -4,     // 买入触发阈值（%）
        totalCapital: 10000,  // 计划总本金
        parts: 10,            // 分成份数，决定每次交易金额 = totalCapital / parts
        lowPositionRatio: 10, // 低仓比例，例如 10 表示 10%，即底仓为 10% 的本金
  
        // 每日记录数组（每个对象代表一天数据）
        result: [],
        // 汇总信息
        summary: null,
        // 延迟交易记录：记录前一日触发的交易金额（T 日信号在 T+1 生效），单位为金额
        delayedActions: {},
        // 全局变量：上一交易日持仓价值 V、累计投入本金、持仓份额
        V: 0,
        invested: 0,
        shares: 0,
        // 网格累计收益率，从建仓次日起累计（内部以小数表示，如 -0.016 表示 -1.6%）
        gridCumulativeYield: 0,
        // ECharts 实例
        chartInstance: null
      }
    },
    methods: {
      runBacktest() {
        // 1. 根据用户选择的日期区间过滤 data.json 数据
        const allDates = data.time;
        const allZdf = data.zdf.map(v => Number(v)); // 每日涨跌幅（%）
        const allPrices = data.num.map(v => Number(v));
        let filtered = [];
        for (let i = 0; i < allDates.length; i++) {
          const d = allDates[i];
          if ((!this.startDate || d >= this.startDate) && (!this.endDate || d <= this.endDate)) {
            filtered.push({
              date: d,
              dailyChange: allZdf[i],
              price: allPrices[i]
            });
          }
        }
        if (filtered.length === 0) {
          alert("所选日期区间内无数据！");
          return;
        }
  
        // 2. 初始化参数
        const gridTradeMoney = this.totalCapital / this.parts;
        // 底仓金额
        const baseInvested = this.totalCapital * (this.lowPositionRatio / 100);
        // 初始持仓、投入本金均为 0
        this.V = 0;
        this.invested = 0;
        this.shares = 0;
        this.delayedActions = {};
        this.gridCumulativeYield = 0;
  
        // 用于保存每日记录和图表数据
        let res = [];
        const chartDates = [];
        const chartHoldValue = [];
        const chartDailyChange = [];
        const chartCumulativeChange = [];
        const buyPoints = [];
        const sellPoints = [];
  
        // 3. 遍历每个交易日（i==0 表示网格开始日）
        for (let i = 0; i < filtered.length; i++) {
          const day = filtered[i];
          chartDates.push(day.date);
  
          // ① 先应用前一日延迟交易：交易在 T+1 日生效
          let effectiveTrade = 0;
          if (this.delayedActions[i] !== undefined) {
            effectiveTrade = this.delayedActions[i];
          }
  
          // ② 计算当日持仓价值：V_today = (上一交易日持仓价值 + 有效交易金额) * (1 + 当天涨跌幅/100)
          let prevV = (i === 0) ? 0 : this.V;
          let V_today = (prevV + effectiveTrade) * (1 + day.dailyChange / 100);
  
          // ③ 当日收益 = V_today - (上一交易日持仓价值 + 有效交易金额)
          let dailyReturn = (i === 0) ? 0 : (V_today - (prevV + effectiveTrade));
  
          // ④ 更新累计投入本金：仅当有有效交易时更新（第一日无）
          if (i > 0) {
            this.invested += effectiveTrade;
          }
  
          // ⑤ 累积收益 = 当日持仓价值 - 累计投入本金
          let totalProfit = V_today - this.invested;
  
          // ⑥ 持仓收益率 = 累积收益 / 累计投入本金；总投资收益率 = V_today/invested - 1
          let holdYield = (this.invested !== 0) ? totalProfit / this.invested : 0;
          let totalYield = (this.invested !== 0) ? V_today / this.invested - 1 : 0;
  
          // ⑦ 更新持仓份额：当天新增份额 = effectiveTrade / 当天价格（卖出为负）
          let newShares = (effectiveTrade !== 0) ? effectiveTrade / day.price : 0;
          this.shares = (i === 0) ? 0 : this.shares + newShares;
  
          // ⑧ 保存当天持仓价值，用于下个交易日计算
          this.V = V_today;
  
          // ⑨ 网格累计收益率：建仓当天不计，从次日开始累计，每日累加当天涨跌（以小数表示）
          if (i === 0) {
            this.gridCumulativeYield = 0;
          } else {
            this.gridCumulativeYield += day.dailyChange / 100;
          }
  
          // ⑩ 判断当天是否触发交易信号（记录信号，不当日生效，延迟至次日）
          // 买入逻辑：当天涨跌幅 ≤ 买入阈值
          // 卖出逻辑：当天涨跌幅 ≥ 卖出阈值 且当前有持仓，并且当前累计投入本金 > 底仓金额
          let operation = '-';
          let currentTrade = 0;
          if (day.dailyChange <= this.buyThreshold) {
            operation = `买入 +${gridTradeMoney}`;
            currentTrade = gridTradeMoney;
            buyPoints.push({ date: day.date, price: day.price });
          } else if (day.dailyChange >= this.sellThreshold && this.shares > 0 && this.invested > baseInvested) {
            // 如果卖出操作可能导致投入本金低于底仓，则只卖到底仓水平
            if (this.invested - gridTradeMoney < baseInvested) {
              currentTrade = -(this.invested - baseInvested);
              operation = `卖出 -${(this.invested - baseInvested).toFixed(0)}`;
            } else {
              currentTrade = -gridTradeMoney;
              operation = `卖出 -${gridTradeMoney}`;
            }
            sellPoints.push({ date: day.date, price: day.price });
          }
          // 将当天触发的交易信号记录到延迟队列，下个交易日生效
          if (currentTrade !== 0) {
            this.delayedActions[i + 1] = currentTrade;
          }
  
          // ⑪ 保存当天记录
          res.push({
            date: day.date,
            operation: operation,
            tradeAmount: currentTrade,         // 当天触发的交易金额（延迟至次日生效）
            holdShares: +this.shares.toFixed(2), // 持仓份额
            holdValue: V_today,                // 当日持仓价值
            invested: this.invested,           // 累计投入本金
            dailyReturn: dailyReturn,          // 当日收益
            holdYield: holdYield,              // 持仓收益率
            dailyChange: day.dailyChange,      // 当天涨跌幅 (%)
            totalProfit: totalProfit,          // 累积收益
            gridCumulativeYield: this.gridCumulativeYield, // 网格累计收益率
            totalYield: totalYield             // 总投资收益率
          });
  
          // ⑫ 更新图表数据
          chartHoldValue.push(V_today);
          chartDailyChange.push(day.dailyChange);
          chartCumulativeChange.push(i === 0 ? day.dailyChange : chartCumulativeChange[i - 1] + day.dailyChange);
        }
  
        this.result = res;
        // 汇总信息：以最后一天记录为准
        const lastDay = res[res.length - 1];
        this.summary = {
          totalInvested: this.invested,
          totalProfit: lastDay.totalProfit,
          holdingDays: res.length,
          totalAsset: lastDay.holdValue,
          totalYield: lastDay.totalYield
        };
  
        // 使用 ECharts 绘制折线图，标注买入/卖出点，同时显示持仓价值、每日涨跌幅和累计涨跌幅
        nextTick(() => {
          if (!this.chartInstance) {
            this.chartInstance = echarts.init(this.$refs.chart);
          }
          const option = {
            tooltip: { trigger: 'axis' },
            legend: {
              data: ['持仓价值', '每日涨跌幅', '累计涨跌幅']
            },
            xAxis: {
              type: 'category',
              data: chartDates
            },
            yAxis: [
              { type: 'value', name: '持仓价值' },
              { type: 'value', name: '涨跌幅 (%)' }
            ],
            series: [
              {
                name: '持仓价值',
                type: 'line',
                data: chartHoldValue,
                yAxisIndex: 0,
                smooth: true,
                markPoint: {
                  data: [
                    ...buyPoints.map(pt => ({
                      name: '买入',
                      value: pt.price,
                      xAxis: pt.date,
                      yAxis: pt.price,
                      itemStyle: { color: 'green' }
                    })),
                    ...sellPoints.map(pt => ({
                      name: '卖出',
                      value: pt.price,
                      xAxis: pt.date,
                      yAxis: pt.price,
                      itemStyle: { color: 'red' }
                    }))
                  ]
                }
              },
              {
                name: '每日涨跌幅',
                type: 'line',
                data: chartDailyChange,
                yAxisIndex: 1,
                smooth: true
              },
              {
                name: '累计涨跌幅',
                type: 'line',
                data: chartCumulativeChange,
                yAxisIndex: 1,
                smooth: true
              }
            ]
          };
          this.chartInstance.setOption(option);
        });
      }
    },
    mounted() {
      // 默认将日期区间设置为 data.json 中的全部日期
      if (data.time && data.time.length) {
        this.startDate = data.time[0];
        this.endDate = data.time[data.time.length - 1];
      }
    }
  }
  </script>
  
  <style scoped>
  .backtest-tool {
    padding: 20px;
    font-family: Arial, sans-serif;
  }
  .controls {
    margin-bottom: 20px;
  }
  .controls label {
    margin-right: 15px;
  }
  .controls input {
    margin-left: 5px;
    padding: 4px;
  }
  button {
    padding: 6px 12px;
    background: #007bff;
    color: #fff;
    border: none;
    cursor: pointer;
  }
  button:hover {
    background: #0056b3;
  }
  table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
  }
  th, td {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: center;
  }
  .summary {
    margin-top: 20px;
    font-size: 16px;
  }
  </style>
  